﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Security.Cryptography;

namespace BluetoothLEWpfDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        BluetoothLEDevice bleDevice = null;
        GattDeviceService subscribeService = null;
        GattCharacteristic gattCharacteristic = null;
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var id = InputId.Text;
            Task.Factory.StartNew(async () =>
            {
                writeLog($"开始连接设备");
                bleDevice = await BluetoothLEDevice.FromIdAsync(id);
                if (bleDevice == null)
                {
                    writeLog($"无法连接设备");
                }
                else
                {
                    writeLog($"设备连接成功");
                    GattDeviceServicesResult result = await bleDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached);
                    if (result.Status == GattCommunicationStatus.Success)
                    {
                        writeLog("查找设备服务成功");
                        foreach (GattDeviceService service in result.Services)
                        {
                            writeLog($"服务:{service.Uuid}");
                            if (service.Uuid == Guid.Parse("0000fff0-0000-1000-8000-00805f9b34fb"))
                            {
                                subscribeService = service;
                            }
                        }
                        if (subscribeService == null)
                        {
                            writeLog($"设备不支持订阅通知服务");
                        }
                        else
                        {
                            //subscribe.IsEnabled = true;
                            var accessStatus = await subscribeService.RequestAccessAsync();
                            if (accessStatus == DeviceAccessStatus.Allowed)
                            {
                                var getresult = await subscribeService.GetCharacteristicsAsync(BluetoothCacheMode.Uncached);
                                if (getresult.Status == GattCommunicationStatus.Success)
                                {
                                    var characteristics = getresult.Characteristics;
                                    foreach (GattCharacteristic item in characteristics)
                                    {
                                        writeLog($"服务特性:{item.Uuid},{item.CharacteristicProperties}");
                                        if (item.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Indicate) ||
                                        item.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
                                            gattCharacteristic = item;
                                    }
                                    if (gattCharacteristic == null)
                                    {
                                        writeLog($"没有找到可订阅的服务特性");
                                    }
                                    else
                                    {
                                        Dispatcher.Invoke(() =>
                                        {
                                            subscribe.IsEnabled = true;
                                        });
                                    }
                                }
                                else
                                {
                                    writeLog($"服务特性读取失败.{getresult.Status}");
                                }
                            }
                            else
                            {
                                writeLog($"访问订阅通知服务失败.{accessStatus.ToString()}");
                            }
                        }
                    }
                    else
                    {
                        writeLog("Device unreachable");
                    }
                }

            }).ContinueWith(task =>
            {
                if (task.Exception != null)
                {
                    writeLog($"{task.Exception.Message}{Environment.NewLine}{task.Exception.StackTrace}");
                    if (task.Exception.InnerException != null)
                    {
                        writeLog($"{task.Exception.InnerException.Message}{Environment.NewLine}{task.Exception.InnerException.StackTrace}");

                    }
                }
            });
        }

        private void writeLog(string msg)
        {
            Dispatcher.Invoke(() =>
            {
                log.AppendText($"[{DateTime.Now:HH:mm:ss}]{msg}{Environment.NewLine}");
                log.ScrollToEnd();
            });
        }

        private bool isSubscribe = false;
        private void subscribe_Click(object sender, RoutedEventArgs e)
        {
            if (!isSubscribe)
            {
                Task.Factory.StartNew(async () =>
                {
                    GattCommunicationStatus status = GattCommunicationStatus.Unreachable;
                    var cccdValue = GattClientCharacteristicConfigurationDescriptorValue.None;
                    if (gattCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Indicate))
                    {
                        cccdValue = GattClientCharacteristicConfigurationDescriptorValue.Indicate;
                    }

                    else if (gattCharacteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
                    {
                        cccdValue = GattClientCharacteristicConfigurationDescriptorValue.Notify;
                    }

                    try
                    {
                        // BT_Code: Must write the CCCD in order for server to send indications.
                        // We receive them in the ValueChanged event handler.
                        status = await gattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(cccdValue);

                        if (status == GattCommunicationStatus.Success)
                        {
                            gattCharacteristic.ValueChanged += GattCharacteristic_ValueChanged;
                            isSubscribe = true;
                            Dispatcher.Invoke(() =>
                            {
                                subscribe.Content = "取消订阅";
                            });
                            writeLog("订阅成功");
                        }
                        else
                        {
                            writeLog($"订阅失败: {status}");
                        }
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        // This usually happens when a device reports that it support indicate, but it actually doesn't.
                        writeLog(ex.Message);
                    }
                });
            }
            else
            {
                Task.Factory.StartNew(async () =>
                {
                    try
                    {
                        // BT_Code: Must write the CCCD in order for server to send notifications.
                        // We receive them in the ValueChanged event handler.
                        // Note that this sample configures either Indicate or Notify, but not both.
                        var result = await
                                gattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
                                    GattClientCharacteristicConfigurationDescriptorValue.None);
                        if (result == GattCommunicationStatus.Success)
                        {
                            isSubscribe = false;
                            gattCharacteristic.ValueChanged -= GattCharacteristic_ValueChanged;
                            writeLog("取消订阅成功");
                        }
                        else
                        {
                            writeLog($"取消订阅失败: {result}");
                        }
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        // This usually happens when a device reports that it support notify, but it actually doesn't.
                        writeLog(ex.Message);
                    }
                });
            }
        }

        private void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            CryptographicBuffer.CopyToByteArray(args.CharacteristicValue, out byte[] buffers);
            writeLog($"收到数据:{byteToHexStr(buffers)}. 长度:{args.CharacteristicValue.Length}.");
            if (buffers.Length == 17)
            {
                writeLog($"体温:{ ((buffers[9] << 8 | buffers[10] & 0xFF) / 10.0F)},卡号:{buffers[5]} {buffers[6]} { buffers[7]} { buffers[8]}");
            }
        }

        private string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2") + " ";
                }
            }
            return returnStr;
        }

        private void scandevice_Click(object sender, RoutedEventArgs e)
        {
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" };
            string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
            var deviceWatcher =
                     DeviceInformation.CreateWatcher(
                         aqsAllBluetoothLEDevices,
                         requestedProperties,
                         DeviceInformationKind.AssociationEndpoint);
            deviceWatcher.Added += DeviceWatcher_Added;
            deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
            deviceWatcher.Removed += DeviceWatcher_Removed;
            deviceWatcher.Stopped += DeviceWatcher_Stopped;
            deviceWatcher.Updated += DeviceWatcher_Updated;
            deviceWatcher.Start();
        }

        private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
        {
            writeLog($"DeviceWatcher_Updated      Id: {args.Id}    {args.Kind}");
        }

        private void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
        {
            writeLog($"DeviceWatcher_Stopped");
        }

        private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
        {
            writeLog($"DeviceWatcher_RemovedId: {args.Id}    {args.Kind}");
        }

        private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
        {
            writeLog($"DeviceWatcher_EnumerationCompleted");
        }

        private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
        {
            writeLog($"设备名称:[{args.Name}]      Id: {args.Id}    {args.Kind}");
        }
    }
}
